package co.edu.uniandes.ecos.itera.tsp.mundo;

import co.edu.uniandes.ecos.itera.tsp.anotaciones.Avance;
import co.edu.uniandes.ecos.itera.tsp.anotaciones.Interrupciones;
import co.edu.uniandes.ecos.itera.tsp.anotaciones.Loc;
import co.edu.uniandes.ecos.itera.tsp.anotaciones.LogT;
import co.edu.uniandes.ecos.itera.tsp.anotaciones.LogInt;
import co.edu.uniandes.ecos.itera.tsp.anotaciones.Tiempos;
import co.edu.uniandes.ecos.itera.tsp.anotaciones.LogD;

import java.io.Serializable;
import java.util.Hashtable;

/**
 * Representa a una tarea que se debe realizar en un ciclo de un proyecto
 */
@Avance(taskId=7, termino='S')
@Tiempos({
	@LogT(date="2011-03-13", min=12, taskId=7),
	@LogT(date="2011-03-19", min=10, taskId=17),
	@LogT(date="2011-03-19", min=5, taskId=7)
})
@Interrupciones({
	@LogInt(date="2011-03-19",intId=4,min=36,taskId=17)
})
public class Tarea implements Serializable 
{
	/**
	 * Identifica a este objeto como unico
	 */
	private static final long serialVersionUID = -282243327404679389L;
	
	/**
	 * Codigo de la Tarea
	 */
	private int codigo;
	
	/**
	 * Descripcion de la tarea
	 */
	private String descripcion;
	
	/**
	 * Minutos estimado para la realizacion de esta tarea
	 */
	private int minutosEstimados;
	
	/**
	 * Lineas de Codigo estimadas para esta tarea
	 */
	private int lineasDeCodigoEstimadas;
	
	/**
	 * Minutos que realmente tomo realizar esta tarea
	 */
	private int minutosReales;
	
	/**
	 * Lineas de Codigo reales de esta tarea
	 */
	private int lineasDeCodigoReales;
	
	/**
	 * Desarrollador encargado de realizar esta tarea
	 */
	private Desarrollador desarrollador;

	/**
	 * Etapa en donde se desarrolla esta tarea
	 */
	private Etapa etapa;
	
	/**
	 * Determina si la tarea ya ha sido terminada
	 */
	private boolean terminada;
	
	/**
	 * Defectos asociados a esta tarea
	 */
	private Hashtable<Defecto, Hashtable<Etapa, Integer>> defectos;
	
	/**
	 * Interrupciones ocurridas durante la ejecucion de esta tarea
	 */
	private Hashtable<Interrupcion, Integer> interrupciones;
	
	/**
	 * Constructor por defecto de tarea
	 */
	public Tarea()
	{
		this.terminada = false;
		this.defectos = new Hashtable<Defecto, Hashtable<Etapa,Integer>>();
		this.interrupciones = new Hashtable<Interrupcion, Integer>();
	}
	
	/**
	 * Establece el Codigo de la Tarea
	 * @param codigo Codigo de la Tarea
	 */
	@Loc(size=1, taskId=7)
	public void setCodigo(int codigo) 
	{
		this.codigo = codigo;
	}

	/**
	 * Consulta el Codigo de la Tarea
	 * @return Codigo de la Tarea
	 */
	@Loc(size=1, taskId=7)
	public int getCodigo() 
	{
		return codigo;
	}

	/**
	 * Establece el Descripcion de la tarea
	 * @param descripcion Descripcion de la tarea
	 */
	@Loc(size=1, taskId=7)
	public void setDescripcion(String descripcion) 
	{
		this.descripcion = descripcion;
	}

	/**
	 * Consulta el Descripcion de la tarea
	 * @return Descripcion de la tarea
	 */
	@Loc(size=1, taskId=7)
	public String getDescripcion() 
	{
		return descripcion;
	}

	/**
	 * Establece los Minutos estimado para la realizacion de esta tarea
	 * @param minutosEstimados Minutos estimado para la realizacion de esta tarea
	 */
	@Loc(size=1, taskId=7)
	public void setMinutosEstimados(int minutosEstimados) 
	{
		this.minutosEstimados = minutosEstimados;
	}

	/**
	 * Consula los Minutos estimado para la realizacion de esta tarea
	 * @return Minutos estimado para la realizacion de esta tarea
	 */
	@Loc(size=1, taskId=7)
	public int getMinutosEstimados() 
	{
		return minutosEstimados;
	}

	/**
	 * Establece las Lineas de Codigo estimadas para esta tarea
	 * @param lineasDeCodigoEstimadas Lineas de Codigo estimadas para esta tarea
	 */
	@Loc(size=1, taskId=7)
	public void setLineasDeCodigoEstimadas(int lineasDeCodigoEstimadas) 
	{
		this.lineasDeCodigoEstimadas = lineasDeCodigoEstimadas;
	}

	/**
	 * Consula las Lineas de Codigo estimadas para esta tarea
	 * @return Lineas de Codigo estimadas para esta tarea
	 */
	@Loc(size=1, taskId=7)
	public int getLineasDeCodigoEstimadas() 
	{
		return lineasDeCodigoEstimadas;
	}

	/**
	 * Establece los Minutos que realmente tomo realizar esta tarea
	 * @param minutosReales Minutos que realmente tomo realizar esta tarea
	 */
	@Loc(size=1, taskId=7)
	public void setMinutosReales(int minutosReales) 
	{
		this.minutosReales = minutosReales;
	}

	/**
	 * Consula los Minutos que realmente tomo realizar esta tarea
	 * @return Minutos que realmente tomo realizar esta tarea
	 */
	@Loc(size=1, taskId=7)
	public int getMinutosReales() 
	{
		return minutosReales;
	}

	/**
	 * Establece las Lineas de Codigo reales de esta tarea
	 * @param lineasDeCodigoReales Lineas de Codigo reales de esta tarea
	 */
	@Loc(size=1, taskId=7)
	public void setLineasDeCodigoReales(int lineasDeCodigoReales) 
	{
		this.lineasDeCodigoReales = lineasDeCodigoReales;
	}

	/**
	 * Consula las Lineas de Codigo reales de esta tarea
	 * @return Lineas de Codigo reales de esta tarea
	 */
	@Loc(size=1, taskId=7)
	public int getLineasDeCodigoReales() 
	{
		return lineasDeCodigoReales;
	}

	/**
	 * Establece el Desarrollador encargado de realizar esta tarea
	 * @param desarrollador Desarrollador encargado de realizar esta tarea
	 */
	@Loc(size=1, taskId=7)
	public void setDesarrollador(Desarrollador desarrollador) 
	{
		this.desarrollador = desarrollador;
	}

	/**
	 * Consula el Desarrollador encargado de realizar esta tarea
	 * @return Desarrollador encargado de realizar esta tarea
	 */
	@Loc(size=1, taskId=7)
	public Desarrollador getDesarrollador() 
	{
		return desarrollador;
	}

	/**
	 * Establece la etapa en donde se desarrolla esta tarea
	 * @param etapa Etapa en donde se desarrolla esta tarea
	 */
	@Loc(size=1, taskId=7)
	public void setEtapa(Etapa etapa) 
	{
		this.etapa = etapa;
	}

	/**
	 * Consula la Etapa en donde se desarrolla esta tarea
	 * @return Etapa en donde se desarrolla esta tarea
	 */
	@Loc(size=1, taskId=7)
	public Etapa getEtapa() 
	{
		return etapa;
	}
	
	/**
	 * Adiciona una cantidad de LOCs ejecutados a esta tarea
	 * @param locs Lineas de codigo ejecutadas a agrear a esta tarea
	 */
	@Loc(size=1, taskId=73)
	void adicionarLOCs(int locs)
	{
		this.lineasDeCodigoReales += locs;
	}
	
	/**
	 * Adiciona tiempo de ejecucion de esta tarea
	 * @param minutos Minutos a agregar
	 */
	@Loc(size=1, taskId=73)
	void adicionarTiempoReal(int minutos)
	{
		this.minutosReales += minutos;
	}
	
	/**
	 * Agrega una interrupcion a esta Tarea
	 * @param interrupcion Interrupcion a agregar
	 * @param minutos Minutos de intrrupcion
	 */
	@Loc(size=8, taskId=73)
	void adicionarInterrupciones(Interrupcion interrupcion, int minutos)
	{
		if(!this.interrupciones.containsKey(interrupcion))
			this.interrupciones.put(interrupcion, minutos);
		else
		{
			int minutosActuales = this.interrupciones.get(interrupcion);
			minutosActuales += minutos;
			this.interrupciones.put(interrupcion, minutosActuales);
		}
	}
	
	/**
	 * Lista las interrupciones de esta Tarea
	 * @return Interrupciones de esta tarea
	 */
	@Loc(size=1, taskId=73)
	public Hashtable<Interrupcion, Integer> listarInterrupciones()
	{
		return this.interrupciones;
	}
	
	/**
	 * Agrega un defecto encontrado al realizar esta tarea
	 * @param defecto Defecto encontrado
	 * @param etapaInyectada Etapa en donde se inyecto el defecto que se ha encontrado al ejecutar esta tarea
	 */
	@Loc(size=8, taskId=73)
	@LogD(etapaInyectada=Etapa.DISENO, idDefecto=4, taskId=73)
	void adicionarDefecto(Defecto defecto, Etapa etapaInyectada)
	{
		Hashtable<Etapa, Integer> etapa;
		
		if(!this.defectos.containsKey(defecto))
		{
			etapa = new Hashtable<Etapa, Integer>();
			this.defectos.put(defecto, etapa);
		}
		else
			etapa = this.defectos.get(defecto);
		
		if(!etapa.containsKey(etapaInyectada))
			etapa.put(etapaInyectada, 1);
		else
		{
			int veces = etapa.get(etapaInyectada);
			veces++;
			etapa.put(etapaInyectada, veces);
		}
	}
	
	/**
	 * Lista los defectos de esta tarea
	 * @return Defectos de esta tarea
	 */
	@Loc(size=1, taskId=73)
	public Hashtable<Defecto, Hashtable<Etapa, Integer>> listarDefectos()
	{
		return this.defectos;
	}
	
	/**
	 * Termina esta tarea
	 */
	@Loc(size=1, taskId=73)
	void terminar()
	{
		this.terminada = true;
	}
	
	/**
	 * Determina si esta tarea se ha terminado
	 * @return True si se ha terminado, false de lo contrario
	 */
	@Loc(size=1, taskId=73)
	@LogD(etapaInyectada = Etapa.DESARROLLO, idDefecto = 2, taskId = 111)
	public boolean seHaTerminado()
	{
		return this.terminada;
	}
	
	@Override
	public String toString()
	{
		return String.format("%s", this.descripcion);
	}
	
	/**
	 * Se encarga de establecer en ceros los datos
	 * que se calculan en el momento de realizar un cargue
	 * de archivo o directorio de java
	 */
	@Loc(size=5, taskId=962)
	void reestablecerEnCerosParaRecalcular()
	{
		this.minutosReales = 0;
		this.lineasDeCodigoReales = 0;
		this.defectos.clear();
		this.interrupciones.clear();
		this.terminada = false;
	}
	
}
